package visualization;

import optimizers.ganeat.math.ConstantsMath;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.chart.ChartUtilities;

import common.Static;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.datatransfer.*;
import java.awt.Toolkit;

public class PlotExpData extends JPanel {

	/**
	 * Constructs the demo application.
	 * 
	 * @param title
	 *            the frame title.
	 */
	/*
	 * public PlotExpData(final String title) { super(title); XYDataset dataset
	 * = createSampleDataset(); JFreeChart chart =
	 * ChartFactory.createXYLineChart( title, "Time", "Expression Level",
	 * dataset, PlotOrientation.VERTICAL, true, false, false ); XYPlot plot =
	 * (XYPlot) chart.getPlot(); //XYLineAndShapeRenderer renderer = new
	 * XYLineAndShapeRenderer(); //renderer.setSeriesLinesVisible(0, true);
	 * //renderer.setSeriesShapesVisible(0, true);
	 * //renderer.setSeriesLinesVisible(1, false);
	 * //renderer.setSeriesShapesVisible(1, true); //plot.setRenderer(renderer);
	 * final ChartPanel chartPanel = new ChartPanel(chart);
	 * //chartPanel.setPreferredSize(new java.awt.Dimension(800, 800));
	 * setContentPane(chartPanel); }
	 */
	public PlotExpData(final String title, double expData[][]) {
		this(title, expData, 1.0, 1.0, null, "chart", "X", "Y", false, 0, 0);
	}

	public PlotExpData(final String title, double[][] expData,
			String[] geneNames, String xAxis, String yAxis) {
		this(title, expData, 0.0, 1.0, geneNames, "chart", xAxis, yAxis, false,
				0, 0);
	}

	public PlotExpData(final String title, double[][] expData,
			String[] geneNames, String xAxis, String yAxis, double xStart,
			double xStep, boolean buttonCopyData, double maxY, double tick) {
		this(title, expData, xStart, xStep, geneNames, "chart", xAxis, yAxis,
				buttonCopyData, maxY, tick);
	}

	public PlotExpData(final String title, double[][] expData,
			String[] geneNames, Color[] color, Stroke[] stroke, String xAxis,
			String yAxis) {
		this(title, expData, 0.0, 1.0, geneNames, color, stroke, "chart",
				xAxis, yAxis);
	}

	public PlotExpData(final String title, final double expData[][],
			final double[] xData, final String geneNames[], String fName,
			String xAxis, String yAxis, boolean buttonCopyData, double maxY,
			double tick) {
		XYDataset dataset = createSampleDataset(expData, xData, geneNames);
		JFreeChart chart = ChartFactory.createXYLineChart(title, xAxis, yAxis,
				dataset, PlotOrientation.VERTICAL, true, false, false);
		// XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
		// renderer.setSeriesLinesVisible(0, true);
		// renderer.setSeriesShapesVisible(0, true);
		// renderer.setSeriesLinesVisible(1, false);
		// renderer.setSeriesShapesVisible(1, true);
		// plot.setRenderer(renderer);
		final ChartPanel chartPanel = new ChartPanel(chart);
		XYPlot plot = (XYPlot) chart.getPlot();
		if (maxY > 0) {
			NumberAxis range = (NumberAxis) plot.getRangeAxis();
			range.setRange(0.0, maxY);
			range.setTickUnit(new NumberTickUnit(tick));
		}
		if (ConstantsMath.logScale) {
			LogAxis logAxis = new LogAxis(xAxis);
			logAxis.setBase(10);
			plot.setDomainAxis(logAxis);
		}
		//LogAxis logAxis = new LogAxis(yAxis);
		//logAxis.setBase(10);
		//plot.setRangeAxis(logAxis);
		// plot.setDomainGridlinesVisible(false);
		// plot.setRangeGridlinesVisible(false);
		plot.setBackgroundPaint(Color.white);
		for (int i = 0; i < expData.length; i++) {
			plot.getRenderer().setSeriesPaint(i, Static.colors[i / 2]);
		}
		BasicStroke[] strokes = new BasicStroke[] {
				new BasicStroke(2),
				new BasicStroke(2, BasicStroke.CAP_ROUND,
						BasicStroke.JOIN_ROUND, 2, new float[] { 4, 4 }, 4) };
		for (int i = 0; i < expData.length; i++) {
			plot.getRenderer().setSeriesStroke(i, strokes[i%2]);
		}
		chartPanel.setPreferredSize(new java.awt.Dimension(500, 300));
		// setContentPane(chartPanel);
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		this.add(chartPanel);
		if (buttonCopyData) {
			JButton button = new JButton("Copy data to clipboard");
			button.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					StringBuilder builder = new StringBuilder();
					builder.append("X-Values,");
					for (int j = 0; j < xData.length; j++) {
						builder.append(xData + ",");
					}
					builder.append("\r\n");
					for (int i = 0; i < expData.length; i++) {
						builder.append(geneNames[i] + ",");
						for (int j = 0; j < expData[0].length; j++) {
							builder.append(expData[i][j] + ",");
						}
						builder.append("\r\n");
					}
					StringSelection stringSelection = new StringSelection(
							builder.toString());
					Clipboard clpbrd = Toolkit.getDefaultToolkit()
							.getSystemClipboard();
					clpbrd.setContents(stringSelection, null);
					JOptionPane.showMessageDialog(common.Static.frame,
							"Data copied to clipboard.");
				}
			});
			button.setAlignmentX(Component.CENTER_ALIGNMENT);
			this.add(button);
		}
		if (fName != null) {
			// Save the chart
			try {
				ChartUtilities.saveChartAsJPEG(new File(fName + ".jpg"), chart,
						500, 300);
			} catch (Exception e) {
				System.err.println("Problem occurred saving chart.");
			}
		}

	}

	public PlotExpData(final String title, final double expData[][],
			final double Xstart, final double Xstep, final String geneNames[],
			String fName, String xAxis, String yAxis, boolean buttonCopyData,
			double maxY, double tick) {

		// super(title);
		XYDataset dataset = createSampleDataset(expData, Xstart, Xstep,
				geneNames);
		JFreeChart chart = ChartFactory.createXYLineChart(title, xAxis, yAxis,
				dataset, PlotOrientation.VERTICAL, true, false, false);
		// XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
		// renderer.setSeriesLinesVisible(0, true);
		// renderer.setSeriesShapesVisible(0, true);
		// renderer.setSeriesLinesVisible(1, false);
		// renderer.setSeriesShapesVisible(1, true);
		// plot.setRenderer(renderer);
		final ChartPanel chartPanel = new ChartPanel(chart);
		XYPlot plot = (XYPlot) chart.getPlot();
		if (maxY > 0) {
			NumberAxis range = (NumberAxis) plot.getRangeAxis();
			range.setRange(0.0, maxY);
			range.setTickUnit(new NumberTickUnit(tick));
		}
		// plot.setDomainGridlinesVisible(false);
		// plot.setRangeGridlinesVisible(false);
		plot.setBackgroundPaint(Color.white);
		BasicStroke stroke = new BasicStroke(2);
		for (int i = 0; i < expData.length; i++) {
			plot.getRenderer().setSeriesStroke(i, stroke);
		}
		chartPanel.setPreferredSize(new java.awt.Dimension(500, 300));
		// setContentPane(chartPanel);
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		this.add(chartPanel);
		if (buttonCopyData) {
			JButton button = new JButton("Copy data to clipboard");
			button.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					StringBuilder builder = new StringBuilder();
					builder.append("X-Values,");
					double value = Xstart;
					for (int j = 0; j < expData[0].length; j++) {
						builder.append(value + ",");
						value += Xstep;
					}
					builder.append("\r\n");
					for (int i = 0; i < expData.length; i++) {
						builder.append(geneNames[i] + ",");
						for (int j = 0; j < expData[0].length; j++) {
							builder.append(expData[i][j] + ",");
						}
						builder.append("\r\n");
					}
					StringSelection stringSelection = new StringSelection(
							builder.toString());
					Clipboard clpbrd = Toolkit.getDefaultToolkit()
							.getSystemClipboard();
					clpbrd.setContents(stringSelection, null);
					JOptionPane.showMessageDialog(common.Static.frame,
							"Data copied to clipboard.");
				}
			});
			button.setAlignmentX(Component.CENTER_ALIGNMENT);
			this.add(button);
		}
		if (fName != null) {
			// Save the chart
			try {
				ChartUtilities.saveChartAsJPEG(new File(fName + ".jpg"), chart,
						500, 300);
			} catch (Exception e) {
				System.err.println("Problem occurred saving chart.");
			}
		}

	}

	public PlotExpData(final String title, double expData[][], double Xstart,
			double Xstep, String geneNames[], Color[] color, Stroke[] stroke,
			String fName, String xAxis, String yAxis) {

		// super(title);
		XYDataset dataset = createSampleDataset(expData, Xstart, Xstep,
				geneNames);
		JFreeChart chart = ChartFactory.createXYLineChart(title, xAxis, yAxis,
				dataset, PlotOrientation.VERTICAL, true, false, false);
		XYPlot plot = (XYPlot) chart.getPlot();
		for (int i = 0; i < color.length; i++) {
			plot.getRenderer().setSeriesPaint(i, color[i]);
		}
		for (int i = 0; i < stroke.length; i++) {
			plot.getRenderer().setSeriesStroke(i, stroke[i]);
		}
		// XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
		// renderer.setSeriesLinesVisible(0, true);
		// renderer.setSeriesShapesVisible(0, true);
		// renderer.setSeriesLinesVisible(1, false);
		// renderer.setSeriesShapesVisible(1, true);
		// plot.setRenderer(renderer);
		final ChartPanel chartPanel = new ChartPanel(chart);
		chartPanel.setPreferredSize(new java.awt.Dimension(500, 330));
		// setContentPane(chartPanel);
		this.add(chartPanel);

		if (fName != null) {
			// Save the chart
			try {
				ChartUtilities.saveChartAsJPEG(new File(fName + ".jpg"), chart,
						500, 300);
			} catch (Exception e) {
				System.err.println("Problem occurred saving chart.");
			}
		}

	}

	private XYDataset createSampleDataset(double expData[][], double Xstart,
			double Xstep, String geneNames[]) {
		XYSeriesCollection dataset = new XYSeriesCollection();
		for (int gene = 0; gene < expData.length; ++gene) {
			XYSeries series;
			if (geneNames == null) {
				series = new XYSeries("Gene " + (gene + 1));
			} else {
				series = new XYSeries(geneNames[gene]);
			}
			double t = Xstart;
			for (int sample = 0; sample < expData[gene].length; ++sample, t += Xstep) {
				series.add(t, expData[gene][sample]);
			}
			dataset.addSeries(series);
		}
		return dataset;
	}

	private XYDataset createSampleDataset(double expData[][], double[] xData,
			String geneNames[]) {
		XYSeriesCollection dataset = new XYSeriesCollection();
		for (int gene = 0; gene < expData.length; ++gene) {
			XYSeries series;
			if (geneNames == null) {
				series = new XYSeries("Gene " + (gene + 1));
			} else {
				series = new XYSeries(geneNames[gene]);
			}
			for (int sample = 0; sample < xData.length; sample++) {
				series.add(xData[sample], expData[gene][sample]);
			}
			dataset.addSeries(series);
		}
		return dataset;
	}

	/**
	 * Starting point for the demonstration application.
	 * 
	 * @param args
	 *            ignored.
	 */
	/*
	 * /** Creates a sample dataset.
	 * 
	 * @return A dataset.
	 */
	/*
	 * private XYDataset createSampleDataset() { XYSeries series1 = new
	 * XYSeries("Series 1"); series1.add(1.0, 3.3); series1.add(2.0, 4.4);
	 * series1.add(3.0, 1.7); XYSeries series2 = new XYSeries("Series 2");
	 * series2.add(1.0, 7.3); series2.add(2.0, 6.8); series2.add(3.0, 9.6);
	 * series2.add(4.0, 5.6); XYSeriesCollection dataset = new
	 * XYSeriesCollection(); dataset.addSeries(series1);
	 * dataset.addSeries(series2); return dataset; }
	 */
	public static void main(final String[] args) {

		JPanel panel = new JPanel();
		JFrame frame = new JFrame("");
		frame.add(panel);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(1500, 600);
		double[][] data = new double[][] { { 1, 2, 3 }, { 4, 5, 6 } };
		PlotExpData demo = new PlotExpData("", data);
		panel.add(demo);
		frame.show();

	}

}
